package com.tracy.life.utils;

import android.content.Context;
import android.os.Environment;
import android.os.Handler;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * Created by tracy on 2016/7/13.
 */
public class OKHttpUtils {
    private static OKHttpUtils mInstance;
    private OkHttpClient mOkHttpClient;
    private Handler mHandler;
    //构造方法私有化
    public OkHttpClient getOkHttpClient() {
        return mOkHttpClient;
    }

    //初始化一些信息
    private OKHttpUtils(Context context) {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        int cacheSize = 10 << 20;//10Mb
        mOkHttpClient = builder.cache(new Cache(context.getCacheDir(), cacheSize))
                .connectTimeout(15, TimeUnit.SECONDS) //配合piccaso使用
                .readTimeout(20, TimeUnit.SECONDS) //一般是20s
                .writeTimeout(20, TimeUnit.SECONDS)
                .build();

        mHandler = new Handler();
    }

    //对外暴露方法，获取实例对象
    public static OKHttpUtils newInstance(Context context) {
        if (mInstance == null) {
            synchronized (OKHttpUtils.class) {
                if (mInstance == null) {
                    mInstance = new OKHttpUtils(context);
                }
            }
        }
        return mInstance;
    }

    //GET异步请求方式在子线程
    public void getAsyncData(String url, Callback callback, Object tag) {
        Request.Builder builder = new Request.Builder();
        if (tag != null) {
            builder.tag(tag);
        }
        Request request = builder
                .url(url)
                .build();
        Call call = mOkHttpClient.newCall(request);
        call.enqueue(callback);
    }

    //GET异步请求方式在主线程
    public void getAsyncMainData(String url, final MyCallBack callBack, Object tag) {
        Request.Builder builder = new Request.Builder();
        if (tag != null) {
            builder.tag(tag);
        }
        Request request = builder
                .url(url)
                .build();
        Call call = mOkHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                handlerFailure(e, callBack);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String result = response.body().string();
                handlerSuccess(result, callBack);
            }
        });
    }

    //POST异步请求在子线程
    public void POSTAsyncData(String url, HashMap<String, String> map, Callback callBack, Object tag) {
        FormBody.Builder builder = new FormBody.Builder();
        if(map!=null&&map.size()!=0) {
            for (Map.Entry<String, String> entry : map.entrySet()) {
                builder.add(entry.getKey(), entry.getValue());
            }
        }
        RequestBody body = builder.build();
        Request.Builder builder1 = new Request.Builder();
        if (tag != null) {
            builder1.tag(tag);
        }
        Request request = builder1.url(url).post(body).build();
        Call call = mOkHttpClient.newCall(request);
        call.enqueue(callBack);
    }

    //POST异步请求在主线程
    public void POSTAsyncMainData(String url, HashMap<String, String> map, final MyCallBack callBack, Object tag) {
        FormBody.Builder builder = new FormBody.Builder();
        if(map!=null&&map.size()!=0) {
            for (Map.Entry<String, String> entry : map.entrySet()) {
                builder.add(entry.getKey(), entry.getValue());
            }
        }
        RequestBody body = builder.build();

        Request.Builder builder1 = new Request.Builder();
        if (tag != null) {
            builder1.tag(tag);
        }
        Request request = builder1.url(url).post(body).build();

        Call call = mOkHttpClient.newCall(request);

        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                handlerFailure(e, callBack);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String result = response.body().string();
                handlerSuccess(result, callBack);
            }
        });

    }

    //请求失败时，回调方法，将MyCallBack的onFailure方法发送到主线程调用
    private void handlerFailure(final IOException e, final MyCallBack callBack) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                callBack.onFailure(e);
            }
        });
    }

    //请求成功时，回调方法，将MyCallBack的onResponse方法发送到主线程调用
    private void handlerSuccess(final String result, final MyCallBack callBack) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                callBack.onResponse(result);
            }
        });
    }

    //取消请求的方法
    public void cancel(Object tag) {
        if (tag != null) {
            for (Call call : mOkHttpClient.dispatcher().runningCalls()) {
                if (tag.equals(call.request().tag())) {//在正在运行的请求队列中查找
                    call.cancel();
                }
            }
            for (Call call : mOkHttpClient.dispatcher().queuedCalls()) {
                if (tag.equals(call.request().tag())) {//在准备中的请求队列中查找
                    call.cancel();
                }
            }
        }
    }

    public interface MyCallBack {
        void onFailure(IOException e);

        void onResponse(String result);
    }

    //在SD卡下面创建filePath目录，写文件名为fileName
    public void write2SDCard(InputStream is, String fileName, String filePath) {
        FileOutputStream fos = null;
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            try {
                File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + filePath, fileName);
                File parentFile = file.getParentFile();
                if (!parentFile.exists()) {
                    parentFile.mkdirs();

                }
                fos = new FileOutputStream(file);
                int n = 0;
                byte[] buf = new byte[2 * 1024];
                while ((n = is.read(buf)) != -1) {
                    fos.write(buf, 0, n);
                }
                fos.flush();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (is != null)
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                if (fos != null)
                    try {
                        fos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
            }
        }
    }

}
